﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint;
using System.Runtime.Remoting;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace AgileShare.Framework.Library.Helpers
{
	/// <summary>
	/// This class contains helper methods for working with SharePoint Web Parts
	/// - All methods should be static
	/// - DO NOT USE SPContext
	/// </summary>
	public class WebPartHelper
	{
		/// <summary>
		/// Check if WebPart exists.
		/// </summary>
		/// <param name="webPartAssembly">The web part assembly.</param>
		/// <param name="webPartType">Type of the web part.</param>
		/// <param name="zoneID">The zone ID.</param>
		/// <param name="manager">The manager.</param>
		/// <returns></returns>
		public static bool WebPartExists(string webPartAssembly, string webPartType, string zoneID, SPLimitedWebPartManager manager)
		{
			for (int i = 0; i < manager.WebParts.Count; i++)
			{
				if (manager.GetZoneID(manager.WebParts[i]) == zoneID
					&& manager.WebParts[i].WebBrowsableObject.GetType().Name.ToString() == webPartType
					&& manager.WebParts[i].WebBrowsableObject.GetType().Assembly.ToString() == webPartAssembly)
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// Check if WebPart exists.
		/// </summary>
		/// <param name="webPartId">The WebPartId.</param>
		/// <param name="zoneID">The zone ID.</param>
		/// <param name="manager">The WebPart manager.</param>
		/// <returns>True if the WebPart exists in the zone, otherwise False.</returns>
		public static bool WebPartExists(string webPartId, string zoneID, SPLimitedWebPartManager manager)
		{
			for (int i = 0; i < manager.WebParts.Count; i++)
			{
				if (manager.GetZoneID(manager.WebParts[i]) == zoneID
					&& manager.WebParts[i].ID == webPartId)
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// Creates the web part.
		/// </summary>
		/// <param name="webPartName">Name of the web part.</param>
		/// <param name="web">The web.</param>
		/// <returns></returns>
		public static System.Web.UI.WebControls.WebParts.WebPart CreateWebPart(string webPartName, SPWeb web)
		{
			SPQuery query = new SPQuery();
			query.Query = String.Format(
				"<Where><Eq><FieldRef Name='FileLeafRef'/><Value Type='File'>{0}</Value></Eq></Where>",
				webPartName);

			SPList webPartGallery = null;

			if (null == web.ParentWeb)
			{
				// This is the root web.
				webPartGallery = web.GetCatalog(
				   SPListTemplateType.WebPartCatalog);
			}
			else
			{
				// This is a sub-web.
				webPartGallery = web.ParentWeb.GetCatalog(
				   SPListTemplateType.WebPartCatalog);
			}

			SPListItemCollection webParts = webPartGallery.GetItems(query);

			string typeName = webParts[0].GetFormattedValue("WebPartTypeName");
			string assemblyName = webParts[0].GetFormattedValue("WebPartAssembly");
			ObjectHandle webPartHandle = Activator.CreateInstance(
				assemblyName, typeName);

			System.Web.UI.WebControls.WebParts.WebPart webPart =
				(System.Web.UI.WebControls.WebParts.WebPart)webPartHandle.Unwrap();
			return webPart;
		}

		/// <summary>
		/// Adds WebParts to a web part zone.
		/// </summary>		
		/// <param name="zoneId">The ID of the zone to add the webparts in.</param>
		/// <param name="startIndex">The start index that the first webpart in the collection will have.</param>
		/// <param name="webPartManager">The webpart manager for the page where the webparts will be added.</param>
		/// <param name="webParts">The webparts to add to the specified zone.</param>
		public static void AddWebParts(string zoneId, int startIndex, SPLimitedWebPartManager webPartManager, params System.Web.UI.WebControls.WebParts.WebPart[] webParts)
		{
			for (int i = 0; i < webParts.Length; i++)
			{
				if (!WebPartExists(webParts[i].ID, zoneId, webPartManager))
				{
					webPartManager.AddWebPart(webParts[i], zoneId, i + startIndex);
				}
			}
		}

		/// <summary>
		/// Removes WebParts from a webpart zone.
		/// </summary>		
		/// <param name="webPartManager">The webpart manager for the page where the webparts will be removed.</param>
		/// <param name="webPartIds">The IDs of the webparts to remove.</param>		
		public static void RemoveWebParts(SPLimitedWebPartManager webPartManager, params string[] webPartIds)
		{
			List<System.Web.UI.WebControls.WebParts.WebPart> webParts =
				webPartManager.WebParts.Cast<System.Web.UI.WebControls.WebParts.WebPart>().Where(x => webPartIds.Contains(x.ID))
				.ToList();

			foreach (System.Web.UI.WebControls.WebParts.WebPart webPart in webParts)
			{
				webPartManager.DeleteWebPart(webPart);
			}
		}

		/// <summary>
		/// Creates an XsltListViewWebPart object.
		/// </summary>
		/// <param name="webPartId">The ID of the webpart.</param>
		/// <param name="displayName">The display name of the webpart.</param>
		/// <param name="partChromeType">The chrome type of the webpart.</param>
		/// <param name="list">The List that the XsltListViewWebPart will show.</param>
		/// <param name="viewName">The name of the View that the XsltListViewWebPart will show.</param>
		/// <returns>An XsltListViewWebPart object.</returns>
		public static XsltListViewWebPart CreateXsltListViewWebPart(string webPartId, string displayName, PartChromeType partChromeType, SPList list, string viewName)
		{
			Microsoft.SharePoint.WebPartPages.XsltListViewWebPart webPart = new Microsoft.SharePoint.WebPartPages.XsltListViewWebPart();
			webPart.ChromeType = partChromeType;
			webPart.ID = (webPartId != null ? webPartId : list.Views[viewName].ID.ToString("B").ToUpper().TrimStart('{').TrimEnd('}'));
			webPart.DisplayName = displayName;
			webPart.Title = displayName;
			webPart.ListId = list.ID;
			webPart.ViewGuid = list.Views[viewName].ID.ToString("B").ToUpper();
			return webPart;
		}

		/// <summary>
		/// Deletes the web parts.
		/// </summary>
		/// <param name="site">The site.</param>
		/// <param name="webPartFileNames">The web part file names.</param>
		public static void DeleteWebParts(SPSite site, params string[] webPartFileNames)
		{
			string siteUrl = site.ServerRelativeUrl;
			if (siteUrl == "/")
			{
				siteUrl = "";
			}

			SPWeb web = site.RootWeb;

			foreach (string webPartFileName in webPartFileNames)
			{
				SPFile file = web.GetFile(siteUrl + "/_catalogs/wp/" + webPartFileName);
				file.Delete();
			}
		}
	}
}
